package cn.biplam.common.tools;

import java.util.ArrayList;

import cn.biplam.common.wrapper.ErrorMessage;

/**
 * 	动态调用方法接口
 * @author XiaoRuxing
 * @create下午08:43:44
 * @version 1.0
 */
public class CallAction {

	/** 类名或者接口名 */
	private String sClassName;

	/** 构造函数参数类型 */
	@SuppressWarnings("unchecked")
	private Class[] classParamTypes;

	/** 构造函数参数值 */
	private Object[] classParams;

	/** 方法名列表 */
	private ArrayList<String> aMethodName;

	/** 方法参数类型 */
	@SuppressWarnings("unchecked")
	private ArrayList<Class[]> aMethodParamTypes;

	/** 方法参数值 */
	private ArrayList<Object[]> aMethodParams;

	/** 执行所属对象 */
	private Object oMethodObject;

	/** 装载类对象 */
	private CallClass callClass;

	/** 构造函数参数与传入参数类型列表的匹配模式 */
	private char matchModel=Call.MODEL_AUTO_MATCH;

	/**
	 * 构造函数，用于动态执行方法时类构造函数和方法都为无参
	 * @param sClassName 类名
	 * @param sMethodName 方法名
	 * @throws ErrorMessage 
	 */
	@SuppressWarnings("unchecked")
	public CallAction(String sClassName) throws ErrorMessage{
		this(Call.MODEL_NO_MATCH,sClassName,null,null);
	}

	/**
	 * @param 构造函数，用于动态执行方法时类构造和方法都为有参，参数列表可以传入空值
	 * @param sClassName 类名
	 * @param classParamTypes 类构造函数参数类型
	 * @param classParams 类构造函数参数值
	 * @throws ErrorMessage 
	 */
	@SuppressWarnings("unchecked")
	public CallAction(String sClassName,Class[] classParamTypes,
			Object[] classParams) throws ErrorMessage{
		this(Call.MODEL_MANUAL_MATCH,sClassName,classParamTypes,classParams);
	}

	/**
	 * @param 构造函数，用于动态执行方法时类构造和方法都为有参，参数列表可以传入空值，同时可以设置构造函数参数列表的匹配模式
	 * @param sClassName 类名
	 * @param classParamTypes 类构造函数参数类型
	 * @param classParams 类构造函数参数值
	 * @throws ErrorMessage 
	 */
	@SuppressWarnings("unchecked")
	public CallAction(char matchModel,String sClassName,Class[] classParamTypes,
			Object[] classParams) throws ErrorMessage{
		this.sClassName=sClassName;
		this.classParamTypes=classParamTypes;
		this.classParams=classParams;
		this.matchModel=matchModel;
		init();
	}

	/**
	 * 初始化对象
	 * @throws ErrorMessage
	 */
	@SuppressWarnings("unchecked")
	private void init() throws ErrorMessage{
		this.aMethodName=new ArrayList<String>();
		this.aMethodParamTypes=new ArrayList<Class[]>();
		this.aMethodParams=new ArrayList<Object[]>();
		setMethodObject();
	}

	/**
	 * 执行方法
	 * @return 方法执行结果
	 * @throws ErrorMessage
	 */
	@SuppressWarnings("unchecked")
	public Object invoke() throws ErrorMessage{

		/** 结果 */
		Object oResult=null;
		/** 执行方法对象 */
		CallMethod callMethod=null;
		/** 方法名 */
		String sMethodName=null;
		/** 方法参数类型 */
		Class[] methodParamTypes=null;
		/** 方法参数值 */
		Object[] methodParams=null;

		for(int i=0;i<aMethodName.size();i++){
			sMethodName=aMethodName.get(i);
			methodParamTypes=aMethodParamTypes.get(i);
			methodParams=aMethodParams.get(i);
			callMethod=new CallMethod(oMethodObject,sMethodName,methodParamTypes,methodParams);				
			oResult = callMethod.invoke();
		}
		return oResult;
	}

	/**
	 * 添加要执行的方法
	 * @param sMethodName 方法名
	 * @param methodParamTypes 方法参数类型列表
	 * @param methodParams 方法参数值列表
	 */
	@SuppressWarnings("unchecked")
	public void addMethod(String sMethodName,Class[] methodParamTypes,Object[] methodParams){

		aMethodName.add(sMethodName);

		/** 判断参数类型列表是否为空，如果为空则初始化列表 */
		if(methodParamTypes==null||"".equals(methodParamTypes)){
			methodParamTypes=new Class[]{};
		}

		/** 插入参数类型列表 */
		aMethodParamTypes.add(methodParamTypes);

		/** 判断参数值列表是否为空，如果为空则初始化列表 */
		if(methodParams==null||"".equals(methodParams)){
			methodParams=new Object[]{};
		}

		/** 插入参数值列表 */
		aMethodParams.add(methodParams);
	}

	/**
	 * 设置要执行的方法
	 * @param sMethodName 方法名
	 * @param methodParamTypes 方法参数类型列表
	 * @param methodParams 方法参数值列表
	 */
	@SuppressWarnings("unchecked")
	public void setMethod(String sMethodName,Class[] methodParamTypes,Object[] methodParams){

		aMethodName.clear();
		aMethodParamTypes.clear();
		aMethodParams.clear();

		aMethodName.add(sMethodName);

		/** 判断参数类型列表是否为空，如果为空则初始化列表 */
		if(methodParamTypes==null||"".equals(methodParamTypes)){
			methodParamTypes=new Class[]{};
		}

		/** 插入参数类型列表 */
		aMethodParamTypes.add(methodParamTypes);

		/** 判断参数值列表是否为空，如果为空则初始化列表 */
		if(methodParams==null||"".equals(methodParams)){
			methodParams=new Object[]{};
		}

		/** 插入参数值列表 */
		aMethodParams.add(methodParams);
	}

	/**
	 * 设置要执行的方法，在方法为无参方法时适用
	 * @param sMethodName 方法名
	 */
	@SuppressWarnings("unchecked")
	public void setMethod(String sMethodName){
		this.setMethod(sMethodName, null, null);
	}

	/**
	 * 返回当前实例
	 * @return
	 */
	public Object getMethodObject() {
		return oMethodObject;
	}

	/**
	 * 创建当前类实例
	 * @throws ErrorMessage
	 */
	private void setMethodObject() throws ErrorMessage {
		callClass=new CallClass(matchModel,sClassName,classParamTypes,classParams);
		oMethodObject=callClass.getInstance();
	}

	/**
	 * 返回反射类名称
	 * @return
	 */
	public String getClassName() {
		return sClassName;
	}

}
